package tw.right929.utils
{
	/**
	 * 有順序的集合的操作工具。
	 * 有順序的集合(以從0開始的連續整數為索引)
	 * 應具有length:uint屬性，
	 * 及下述方法：
	 * 1.addAt(obj:* , index:int):*
	 * 2.removeAt(index:int):*
	 * 3.getAt(index:int):*
	 */
	public class SequenceCollectionUtil
	{
		public static function mixin(arr:*):void
		{
			arr["push"]			=	pushF;
			arr["pop"]			=	popF;
			arr["unshift"]		=	unshiftF;
			arr["shift"]		=	shiftF;
			arr["getIndex"]		=	getIndexF;
			arr["downIndex"]	=	downIndexF;
			arr["downIndexAt"]	=	downIndexAtF;
			arr["upIndex"]		=	upIndexF;
			arr["upIndexAt"]	=	upIndexAtF;
			arr["swapAt"]		=	swapAtF;
			arr["swap"]			=	swapF;
			arr["moveTo"]		=	moveToF;
			arr["moveToAt"]		=	moveToAtF;
		}
		
		/**
		 * 將傳入的物件加到最後，並傳回新的長度。
		 */
		public static function push(arr:* , ...args):uint
		{
			for(var i:int=0 ; i<args.length ; i++)
				arr.addAt(args[i] , arr.length);
			return arr.length;
		}
		/**
		 * 將傳入的物件加到最後，並傳回新的長度。(mixin專用)
		 */
		public static var pushF:Function	=	function (...args):uint
		{
			args.unshift(this);
			return SequenceCollectionUtil.push.apply(this , args);
		}
		
		/**
		 * 刪除並傳回最後的一個物件。
		 */
		public static function pop(arr:*):*
		{
			if(arr.length <= 0)
				return null;
			return arr.removeAt(arr.length-1);
		}
		/**
		 * 刪除並傳回最後的一個物件。(mixin專用)
		 */
		public static var popF:Function	=	function ():*
		{
			return SequenceCollectionUtil.pop(this);
		}
		
		/**
		 * 將傳入的物件加到最前，並傳回新的長度。
		 */
		public static function unshift(arr:* , ...args):uint
		{
			for(var i:int=args.length-1 ; i>=0 ; i--)
				arr.addAt(args[i] , 0);
			return arr.length;
		}
		/**
		 * 將傳入的物件加到最前，並傳回新的長度。(mixin專用)
		 */
		public static var unshiftF:Function	=	function (...args):uint
		{
			args.unshift(this);
			return SequenceCollectionUtil.unshift.apply(this , args);
		}
		
		/**
		 * 刪除並傳回最前的一個物件。
		 */
		public static function shift(arr:*):*
		{
			if(arr.length <= 0)
				return null;
			return arr.removeAt(0);
		}
		/**
		 * 刪除並傳回最前的一個物件。(mixin專用)
		 */
		public static var shiftF:Function	=	function ():*
		{
			return SequenceCollectionUtil.shift(this);
		}
		
		/**
		 * 取得傳入的obj在arr中的索引位置。
		 */
		public static function getIndex(arr:* , obj:*):int
		{
			for(var i:int=0 ; i<arr.length ; i++)
			{
				if(arr.getAt(i) == obj)
					return i;
			}
			return -1;
		}
		/**
		 * 取得傳入的obj在arr中的索引位置。(mixin專用)
		 */
		public static var getIndexF:Function	=	function (obj:*):int
		{
			return SequenceCollectionUtil.getIndex(this , obj);
		}
		
		/**
		 * 交換傳入物件的索引位置和其索引位置減一的物件。
		 */
		public static function downIndex(arr:* , obj:*):void
		{
			var index:int	=	SequenceCollectionUtil.getIndex(arr , obj);
			SequenceCollectionUtil.downIndexAt(arr , index);
		}
		/**
		 * 交換傳入物件的索引位置和其索引位置減一的物件。(mixin專用)
		 */
		public static var downIndexF:Function	=	function (obj:*):void
		{
			SequenceCollectionUtil.downIndex(this , obj);
		}
		
		/**
		 * 交換傳入的索引位置和索引位置減一的物件。
		 */
		public static function downIndexAt(arr:* , index:int):void
		{
			if(index > 0 && index < arr.length)
				SequenceCollectionUtil.swapAt(arr , index , index-1);
		}
		/**
		 * 交換傳入的索引位置和索引位置減一的物件。(mixin專用)
		 */
		public static var downIndexAtF:Function	=	function (index:int):void
		{
			SequenceCollectionUtil.downIndexAt(this , index);
		}
			
		/**
		 * 交換傳入物件的索引位置和其索引位置加一的物件。
		 */
		public static function upIndex(arr:* , obj:*):void
		{
			var index:int	=	SequenceCollectionUtil.getIndex(arr , obj);
			SequenceCollectionUtil.upIndexAt(arr , index);
		}
		/**
		 * 交換傳入物件的索引位置和其索引位置加一的物件。(mixin專用)
		 */
		public static var upIndexF:Function	=	function (obj:*):void
		{
			SequenceCollectionUtil.upIndex(this , obj);
		}
		
		/**
		 * 交換傳入索引位置和索引位置加一的物件。
		 */
		public static function upIndexAt(arr:* , index:int):void
		{
			if(index < arr.length-1 && index >= 0)
				SequenceCollectionUtil.swapAt(arr , index , index+1);
		}
		/**
		 * 交換傳入索引位置和索引位置加一的物件。(mixin專用)
		 */
		public static var upIndexAtF:Function	=	function (index:int):void
		{
			SequenceCollectionUtil.upIndexAt(this , index);
		}
		
		/**
		 * 交換傳入的二個索引位置的物件。
		 */
		public static function swapAt(arr:* , index1:int , index2:int):void
		{
			if(index1 == index2) return;
			if(index1 < 0 || index1 >= arr.length) return;
			if(index2 < 0 || index2 >= arr.length) return;
			
			if(index1 > index2)
			{
				arr.addAt(arr.removeAt(index1) , index2);
				arr.addAt(arr.removeAt(index2+1) , index1);
			}
			else
			{
				arr.addAt(arr.removeAt(index2) , index1);
				arr.addAt(arr.removeAt(index1+1) , index2);
			}
		}
		/**
		 * 交換傳入的二個索引位置的物件。(mixin專用)
		 */
		public static var swapAtF:Function	=	function (index1:int , index2:int):void
		{
			SequenceCollectionUtil.swapAt(this , index1 , index2);
		}
		
		/**
		 * 交換二個物件的索引位置。
		 */
		public static function swap(arr:* , obj1:* , obj2:*):void
		{
			swapAt(arr , SequenceCollectionUtil.getIndex(arr , obj1) , SequenceCollectionUtil.getIndex(arr , obj2));
		}
		/**
		 * 交換二個物件的索引位置。(mixin專用)
		 */
		public static var swapF:Function	=	function (obj1:* , obj2:*):void
		{
			SequenceCollectionUtil.swap(this , obj1 , obj2);
		}
		
		/**
		 * 改變傳入物件的索引位置。
		 */
		public static function moveTo(arr:* , obj:* , index:int):void
		{
			SequenceCollectionUtil.moveToAt(arr , SequenceCollectionUtil.getIndex(arr , obj) , index);
		}
		/**
		 * 改變傳入物件的索引位置。(mixin專用)
		 */
		public static var moveToF:Function	=	function (obj:* , index:int):void
		{
			SequenceCollectionUtil.moveTo(this , obj , index);
		}
		
		/**
		 * 改變傳入索引位置物件的索引位置。
		 */
		public static function moveToAt(arr:* , oldIndex:int , newIndex:int):void
		{
			if(oldIndex == newIndex) return;
			if(oldIndex < 0 || oldIndex >= arr.length) return;
			if(newIndex < 0 || newIndex >= arr.length) return;
			
			arr.addAt(arr.removeAt(oldIndex) , newIndex);
		}
		/**
		 * 改變傳入索引位置物件的索引位置。(mixin專用)
		 */
		public static var moveToAtF:Function	=	function (oldIndex:int , newIndex:int):void
		{
			SequenceCollectionUtil.moveToAt(this , oldIndex , newIndex);
		}
	}
}